package com.hang.gymmanager.service.impl;

import cn.hutool.core.lang.Snowflake;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hang.gymmanager.Enum.*;
import com.hang.gymmanager.common.BasePageReq;
import com.hang.gymmanager.convert.PojoConvert;
import com.hang.gymmanager.entity.*;
import com.hang.gymmanager.exception.BusinessException;
import com.hang.gymmanager.mapper.CourseMapper;
import com.hang.gymmanager.mapper.OrderMapper;
import com.hang.gymmanager.mapper.WalletMapper;
import com.hang.gymmanager.req.AddCourseRecordReq;
import com.hang.gymmanager.req.AddCourseReq;
import com.hang.gymmanager.req.BuyCourseReq;
import com.hang.gymmanager.req.PageCourseReq;
import com.hang.gymmanager.res.CourseDetailRes;
import com.hang.gymmanager.res.PageCourseRes;
import com.hang.gymmanager.res.UserCoursePageRes;
import com.hang.gymmanager.res.userCourseDetailRes;
import com.hang.gymmanager.service.*;
import com.hang.gymmanager.util.SecurityUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

import static com.hang.gymmanager.Enum.CommonConstant.LINUX_PATH;

@Service
@Slf4j
@RequiredArgsConstructor
public class CourseServiceImpl extends ServiceImpl<CourseMapper, CourseEntity> implements CourseService {

    private final PlaceUseRecordService placeUseRecordService;
    private final CourseRecordService courseRecordService;
    private final CourseMapper courseMapper;
    private final AdminService adminService;

    private final WalletService walletService;
    private final WalletMapper walletMapper;
    private final PojoConvert pojoConvert;
    private final UserCourseRelationService userCourseRelationService;
    private final UserInfoService userInfoService;
    private final OrderMapper orderMapper;
    private final OrderService orderService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer addCourse(AddCourseReq req) {
        //插入课程表
        CourseEntity entity = new CourseEntity();
        BeanUtils.copyProperties(req,entity);
        entity.setStatus(ActivityStatusEnum.WAIT.getValue());
        entity.setCreateUserId(SecurityUtils.getUserId());
        int insert = this.getBaseMapper().insert(entity);
        //list拿出来
        List<AddCourseRecordReq> courseRecords = req.getCourseRecord();
        //list非空判断
        if(courseRecords.size()==0){
            throw new BusinessException("课程小节不能为空");
        }
        //循环。占用场地时间段表，再添加课程小节表
        for(int i=0;i<courseRecords.size();i++){
            AddCourseRecordReq e = courseRecords.get(i);
            QueryWrapper<PlaceUseRecordEntity> useWrapper = new QueryWrapper<>();
            useWrapper.lambda().eq(PlaceUseRecordEntity::getPlaceId,e.getPlaceId())
                    .eq(PlaceUseRecordEntity::getDay,e.getDay())
                    .eq(PlaceUseRecordEntity::getStartTime,e.getStartTime())
                    .eq(PlaceUseRecordEntity::getEndTime,e.getEndTime());
            PlaceUseRecordEntity record = placeUseRecordService.getBaseMapper().selectOne(useWrapper);
            if(record==null){
                throw new BusinessException("时间只能选取七天之内");
            }
            if(record.getRelationId()!=-1){
                throw new BusinessException("场地"+record.getPlaceId()+"--"+record.getStartTime()+"-"+record.getEndTime()+"已经占用");
            }
            record.setStatus(PlaceUseRecordStatusEnum.FUTURE.getValue());
            record.setType(PlaceUseRecordTypeEnum.ACTIVITY.getValue());
            record.setRelationId(entity.getCourseId());
            placeUseRecordService.saveOrUpdate(record);

            //添加小节
            CourseRecordEntity courseRecord = new CourseRecordEntity();
            courseRecord.setCourseId(entity.getCourseId());
            courseRecord.setPlaceId(e.getPlaceId());
            courseRecord.setShouldCount(i+1);
            courseRecord.setStartTime(LocalDateTime.of(e.getDay(),e.getStartTime()));
            courseRecord.setEndTime(LocalDateTime.of(e.getDay(),e.getEndTime()));
            courseRecord.setStatus(CourseSectionStatusEnum.UNSTART.getValue());
            courseRecordService.save(courseRecord);
        }
        return entity.getCourseId();
    }

    @Override
    public Page<PageCourseRes> getPageCourse(PageCourseReq req) {
        Page page = new Page(req.getPageNum(),req.getPageSize());
        Page<PageCourseRes> pageCourse = courseMapper.getPageCourse(req, page);
        return pageCourse;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteCourse(Integer courseId) {
        //先查询课程是不是未进行状态
        CourseEntity course = courseMapper.selectById(courseId);
        if(course.getStatus()!=CourseStatusEnum.WAIT.getValue()){
            throw new BusinessException("课程不是未进行状态，不能删除");
        }
        //先删除场地占用
        QueryWrapper<PlaceUseRecordEntity> placeUseWrapper = new QueryWrapper<>();
        placeUseWrapper.lambda().eq(PlaceUseRecordEntity::getRelationId,courseId)
                .eq(PlaceUseRecordEntity::getType, PlaceUseRecordTypeEnum.COURSE.getValue());
        List<PlaceUseRecordEntity> placeUseRecordEntities = placeUseRecordService.getBaseMapper().selectList(placeUseWrapper);
        placeUseRecordEntities.stream().forEach(e->{
            e.setType(PlaceUseRecordTypeEnum.NONE.getValue());
            e.setRelationId(-1);
            e.setStatus(PlaceUseRecordStatusEnum.FUTURE.getValue());
        });
        placeUseRecordService.saveOrUpdateBatch(placeUseRecordEntities);
        //给用户退款
        QueryWrapper<UserCourseRelationEntity> relationWrapper = new QueryWrapper<>();
        relationWrapper.lambda().eq(UserCourseRelationEntity::getCourseId,courseId);
        List<UserCourseRelationEntity> relationEntities = userCourseRelationService.getBaseMapper().selectList(relationWrapper);
        List<Integer> userIds = relationEntities.stream().map(UserCourseRelationEntity::getUserId).collect(Collectors.toList());
        QueryWrapper<WalletEntity> walletWrapper = new QueryWrapper<>();
        List<WalletEntity> walletEntities = walletMapper.selectList(walletWrapper);
        walletEntities.stream().forEach(e->e.setBalance(e.getBalance().add(course.getCoursePrice())));
        walletService.saveOrUpdateBatch(walletEntities);
        //订单更改
        QueryWrapper<OrderEntity> orderEntityQueryWrapper = new QueryWrapper<>();
        orderEntityQueryWrapper.lambda().eq(OrderEntity::getType,OrderTypeEnum.COURSE.getValue())
                .eq(OrderEntity::getRelationId,courseId);
        List<OrderEntity> orderEntities = orderMapper.selectList(orderEntityQueryWrapper);
        orderEntities.stream().forEach(e->e.setStatus(OrderStatusEnum.REFUND.getValue()));
        orderService.saveOrUpdateBatch(orderEntities);
        //在删除课程小节
        QueryWrapper<CourseRecordEntity> courseWrapper = new QueryWrapper<>();
        courseWrapper.lambda().eq(CourseRecordEntity::getCourseId,courseId);
        courseRecordService.remove(courseWrapper);
        //最后删除课程
        this.removeById(courseId);
    }

    @Override
    public CourseDetailRes detail(Integer courseId) {
        //先找出主体
        CourseEntity entity = this.getBaseMapper().selectById(courseId);
        CourseDetailRes res = new CourseDetailRes();
        BeanUtils.copyProperties(entity,res);
        res.setId(entity.getCourseId());
        res.setPrice(entity.getCoursePrice());
        res.setCreateUserName(adminService.getBaseMapper().selectById(entity.getCreateUserId()).getName());
        //找出对应的所有课程小节
        QueryWrapper<CourseRecordEntity> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(CourseRecordEntity::getCourseId,courseId)
                        .orderByAsc(CourseRecordEntity::getId);
        List<CourseRecordEntity> courseRecordEntities = courseRecordService.getBaseMapper().selectList(wrapper);
        res.setSectionResList(courseRecordEntities);
        return res;
    }

    @Override
    public Page<UserCoursePageRes> userCoursePage(BasePageReq req) {
        Page page = new Page(req.getPageNum(),req.getPageSize());
        QueryWrapper<CourseEntity> wrapper = new QueryWrapper<>();
        wrapper.lambda().orderByDesc(CourseEntity::getStartTime);
        Page info = this.getBaseMapper().selectPage(page, wrapper);
        List<UserCoursePageRes> res = pojoConvert.userCoursePageEntity2Res(info.getRecords());
        info.setRecords(res);
        return info;
    }

    @Override
    public userCourseDetailRes userCourseDetail(Integer courseId) {
        userCourseDetailRes res = new userCourseDetailRes();
        CourseEntity course = this.getBaseMapper().selectById(courseId);
        res.setCourse(course);
        QueryWrapper<CourseRecordEntity> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(CourseRecordEntity::getCourseId, courseId);
        List<CourseRecordEntity> list = courseRecordService.getBaseMapper().selectList(wrapper);
        res.setList(list);
        return res;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public synchronized String buy(BuyCourseReq req) {
        LocalDateTime create = LocalDateTime.now();
        //获取用户id
        Integer userId = SecurityUtils.getUserId();
        UserInfoEntity userInfoEntity = userInfoService.getBaseMapper().selectById(userId);
        //获取课程信息
        CourseEntity courseEntity = this.getBaseMapper().selectById(req.getCourseId());
        if(courseEntity.getStatus()!=CourseStatusEnum.WAIT.getValue()){
            throw new BusinessException("课程已开始或者课程已结束");
        }
        WalletEntity wallet = walletMapper.selectById(userId);
        if(wallet.getBalance().doubleValue()<courseEntity.getCoursePrice().doubleValue()){
            throw new BusinessException("账户余额不足");
        }
        //创建用户课程关联关系
        UserCourseRelationEntity relation = new UserCourseRelationEntity();
        relation.setUserId(userId);
        relation.setCourseId(req.getCourseId());
        userCourseRelationService.getBaseMapper().insert(relation);
        //扣款
        wallet.setBalance(wallet.getBalance().subtract(courseEntity.getCoursePrice()));
        walletMapper.updateById(wallet);
        //插入订单
        OrderEntity order = new OrderEntity();
        Snowflake snowflake = new Snowflake();
        order.setOrderId(snowflake.nextId())
                .setUserId(userId)
                .setUserName(userInfoEntity.getName())
                .setType(OrderTypeEnum.COURSE.getValue())
                .setStatus(OrderStatusEnum.PAYED.getValue())
                .setCreateTime(create)
                .setFinishTime(LocalDateTime.now())
                .setRelationId(req.getCourseId())
                .setPrice(courseEntity.getCoursePrice())
                .setMessage("购买了:"+courseEntity.getCourseName()+"课程");
        orderMapper.insert(order);
        return "购买成功";
    }

    @Override
    public String uploadPic(MultipartFile file) {
        Integer userId = SecurityUtils.getUserId();
        String fileName = null;
        //如果文件为空 报错
        if (file.isEmpty()) {
            throw new BusinessException("文件为空");
        }
        try {
            //获取项目当前路径
//            String url = "D:\\ideaProject";
            String url = LINUX_PATH;
            Path imgPath = Paths.get(url,"img");
            //获取文件字节流文件
            byte[] bytes = file.getBytes();
            //文件id
            String randomString = UUID.randomUUID().toString();
            // 仅保留前 5 个字符作为随机字符串
            String newRan = randomString.substring(0, 5);
            fileName = newRan+"-"+ImgTypeEnum.COURSE.getValue()+".jpg";
            // 构建保存文件的路径
            Path filePath = imgPath.resolve(fileName);
            // 将文件保存到本地
            Files.write(filePath, bytes);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return fileName;
    }


}
